﻿using FreeSql;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using XKPlatform.DataModels.Dao.BaseEntity;
using XKPlatform.DataModels.DBHelper;

namespace XKPlatform.DataModels.Dao.BaseDao
{
    public class BaseFreeSqlDao<T> where T : BaseEntity
    {
        public static DataType DbType = EnumHelper.StringConvertToEnum<DataType>(StaticClass.DbTypeStr ?? "SqlServer");

        /// <summary>
        /// 新增方法
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async virtual Task<long> CountAsync()
        {
            var runsql = DbType.DB().Select<T>();
            return await runsql.CountAsync();
        }

        /// <summary>
        /// 新增方法 自增 返回自增id
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async virtual Task<long> InsertIdentityAsync(T model)
        {
            var runsql = DbType.DB().Insert<T>(model);
            return await runsql.ExecuteIdentityAsync();
        }
        /// <summary>
        /// 新增方法 主键非自增列 返回影响行数
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async virtual Task<long> InsertAsync(T model)
        {
            var runsql = DbType.DB().Insert<T>(model);

            return await runsql.ExecuteAffrowsAsync();
        }

        /// <summary>
        /// 新增方法
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async virtual Task<int> BatchInsertAsync(List<T> models)
        {
            var runsql = DbType.DB().Insert<T>().AppendData(models);
            return await runsql.ExecuteAffrowsAsync();
        }

        /// <summary>
        /// 修改方法
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async virtual Task<bool> UpdateAsync(T model)
        {
            var runsql = DbType.DB().Update<T>().SetSource(model);
            var rows = await runsql.ExecuteAffrowsAsync();
            return rows > 0;
        }

        /// <summary>
        /// 删除方法
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async virtual Task<bool> DeleteAsync(long id)
        {
            var result = await DbType.DB().Delete<T>(id).ExecuteAffrowsAsync();
            return result > 0;
        }

        /// <summary>
        /// 删除方法
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual bool Delete(Expression<Func<T, bool>> where)
        {
            var result = DbType.DB().Delete<T>().Where(where).ExecuteAffrows();
            return result > 0;
        }

        /// <summary>
        /// 删除方法
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async virtual Task<bool> DeleteAsync(Expression<Func<T, bool>> where)
        {
            var result = await DbType.DB().Delete<T>().Where(where).ExecuteAffrowsAsync();
            return result > 0;
        }

        /// <summary>
        /// 获取一条数据
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public async virtual Task<T> GetByOneAsync(Expression<Func<T, bool>> where)
        {
            return await DbType.DB().Select<T>()
                .Where(where).ToOneAsync();
        }

        /// <summary>
        /// 根据条件获取list
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public virtual List<T> GetList(Expression<Func<T, bool>> where)
        {
            var list = DbType.DB().Select<T>()
               .Where(where);

            return list.ToList();
        }

        /// <summary>
        /// 查询方法
        /// </summary>
        /// <param name="where"></param>
        /// <param name="orderby"></param>
        /// <returns></returns>
        public async virtual Task<(List<T> list, long count)> QueryAsync(Expression<Func<T, bool>> where,
             List<SortInfo<T, object>> orderbys = null, PageInfo pageInfo = null)
        {
            //设置查询条件
            var list = DbType.DB().Select<T>()
                .Where(where);

            var count = list.Count();

            BaseEntity baseEntity = new BaseEntity();
            //设置排序
            if (orderbys != null)
            {
                foreach (var item in orderbys)
                {
                    list = item.SortMethods == SortEnum.Asc ? list.OrderBy(item.Orderby) : list.OrderByDescending(item.Orderby);
                }
            }

            //设置分页操作
            if (pageInfo != null && pageInfo.IsPaging)
                list.Skip((pageInfo.PageIndex - 1) * pageInfo.PageSize).Limit(pageInfo.PageSize);
            var resultList = await list.ToListAsync();
            //执行查询
            return (resultList, count);
        }

        #region no Async

        /// <summary>
        /// 新增方法
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public virtual long Count()
        {
            var runsql = DbType.DB().Select<T>();
            return runsql.Count();
        }

        /// <summary>
        /// 新增方法 自增
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public virtual long InsertIdentity(T model)
        {
            var runsql = DbType.DB().Insert<T>(model);
            return runsql.ExecuteIdentity();
        }
        /// <summary>
        /// 新增方法  返回影响行数
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public virtual long InsertAffrows(T model)
        {
            var runsql = DbType.DB().Insert<T>(model);
            return runsql.ExecuteAffrows();
        }

        /// <summary>
        /// 批量新增方法
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public virtual int BatchInsert(List<T> models)
        {
            var runsql = DbType.DB().Insert<T>().AppendData(models);
            return runsql.ExecuteAffrows();
        }

        /// <summary>
        /// 修改方法  根据主键更新
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public virtual bool Update(T model)
        {
            var runsql = DbType.DB().Update<T>().SetSource(model);
            var rows = runsql.ExecuteAffrows();
            return rows > 0;
        }


        /// <summary>
        /// 删除 new {id=1}
        /// </summary>
        /// <param name="dywhere"></param>
        /// <returns></returns>
        public virtual bool Delete(object dywhere)
        {
            var result = DbType.DB().Delete<T>(dywhere).ExecuteAffrows();
            return result > 0;
        }

        /// <summary>
        /// 获取一条数据
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public virtual T GetByOne(Expression<Func<T, bool>> where)
        {
            return DbType.DB().Select<T>()
                .Where(where).ToOne();
        }

        /// <summary>
        /// 查询方法
        /// </summary>
        /// <param name="where"></param>
        /// <param name="orderby"></param>
        /// <returns></returns>
        public virtual (List<T> list, long count) Query(Expression<Func<T, bool>> where,
            List<SortInfo<T, object>> orderbys = null, PageInfo pageInfo = null)
        {
            //设置查询条件
            var list = DbType.DB().Select<T>()
                .Where(where);


            var count = list.Count();

            BaseEntity baseEntity = new BaseEntity();
            //设置排序
            if (orderbys != null)
            {
                foreach (var item in orderbys)
                {
                    list = item.SortMethods == SortEnum.Asc ? list.OrderBy(item.Orderby) : list.OrderByDescending(item.Orderby);
                }
            }

            //设置分页操作
            if (pageInfo != null && pageInfo.IsPaging)
                list.Skip((pageInfo.PageIndex - 1) * pageInfo.PageSize).Limit(pageInfo.PageSize);
            var resultList = list.ToList();
            //执行查询
            return (resultList, count);
        }

        /// <summary>
        /// 执行查询sql
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public List<T> QueryBySql(string sql)
        {
            return DbType.DB().Select<T>()
                 .WithSql(sql).ToList();
        }

        /// <summary>
        /// 执行自定义查询sql 分页查询
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="startIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public List<T> QueryBySqlPage(string sql, int startIndex, int pageSize)
        {
            return DbType.DB().Select<T>()
                .WithSql(sql)
                .Page(startIndex, pageSize).ToList();
        }
        /// <summary>
        /// _iservice.UpdateBySets(o => o.ID == save.ID).Set(a => a.UserName == "ceshi").Set(a => a.IPAddress == "12222").ExecuteAffrows();
        /// 返回更新指定列对象 在返回对象上 .set(a=>a.columnName==value)  .  .ExecuteAffrows();  返回影响行数
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public IUpdate<T> UpdateBySet(Expression<Func<T, bool>> where)
        {
            var update = DbType.DB().Update<T>().Where(where);
            return update;
        }

        /// <summary>
        /// 更新指定列 dic 传输数据
        /// </summary>
        /// <param name="where"></param>
        /// <param name="dic"></param>
        /// <returns></returns>
        public int UpdateColumns(Expression<Func<T, bool>> where, Dictionary<string, object> dic)
        {
            var runsql = DbType.DB().Update<T>()
                 .SetDto(dic)
                 .Where(where);
            var count = runsql.ExecuteAffrows();
            return count;
        }


        //执行存储过程TODO


        /// <summary>
        /// 根据lambda表达式更新实体 忽略更新列
        /// </summary>
        /// <param name="model"></param>
        /// <param name="where"></param>
        /// <returns></returns>
        public virtual bool Update(T model, Expression<Func<T, bool>> where, Expression<Func<T, object>> IgnoreLmbad = null)
        {
            if (IgnoreLmbad != null)
            {
                var runsql = DbType.DB().Update<T>().SetSource(model).IgnoreColumns(IgnoreLmbad).Where(where);
                var rows = runsql.ExecuteAffrows();
                return rows > 0;
            }
            else
            {
                var runsql = DbType.DB().Update<T>().SetSource(model).Where(where);
                var rows = runsql.ExecuteAffrows();
                return rows > 0;
            }
        }
        /// <summary>
        /// 更新指定列
        /// </summary>
        /// <param name="model"></param>
        /// <param name="where"></param>
        /// <returns></returns>
        public virtual bool UpdateCol(T model, Expression<Func<T, bool>> where)
        {
            var cout = DbType.DB().Update<T>().SetDto(model)
                 .Where(where)
                 .ExecuteAffrows();
            return cout > 0;
        }


        #endregion

        #region 仓储分表模式
        /// <summary>
        /// 获取数量
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async virtual Task<long> CountAsync(string tableName)
        {
            var runsql = DbType.DB().GetGuidRepository<T>(null, oldName => tableName).Select;
            return await runsql.CountAsync();
        }

        /// <summary>
        /// 新增方法
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async virtual Task<T> InsertAsync(T model, string tableName)
        {
            var runsql = DbType.DB().GetGuidRepository<T>(null, oldName => tableName);
            return await runsql.InsertAsync(model);
        }


        /// <summary>
        /// 新增方法
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async virtual Task<List<T>> BatchInsertAsync(List<T> models, string tableName)
        {
            var runsql = DbType.DB().GetGuidRepository<T>(null, oldName => tableName);
            return await runsql.InsertAsync(models);
        }

        /// <summary>
        /// 修改方法
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async virtual Task<bool> UpdateAsync(T model, string tableName)
        {
            var runsql = DbType.DB().GetGuidRepository<T>(null, oldName => tableName);
            int rows = await runsql.UpdateAsync(model);

            return rows > 0;
        }

        /// <summary>
        /// 删除方法
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async virtual Task<bool> DeleteAsync(Guid id, string tableName)
        {
            var runsql = DbType.DB().GetGuidRepository<T>(null, oldName => tableName);
            var result = await runsql.DeleteAsync(id);
            return result > 0;
        }



        /// <summary>
        /// 删除方法
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async virtual Task<bool> DeleteAsync(Expression<Func<T, bool>> where, string tableName)
        {
            var runsql = DbType.DB().GetGuidRepository<T>(null, oldName => tableName);
            var result = await runsql.DeleteAsync(where);
            return result > 0;
        }

        /// <summary>
        /// 获取一条数据
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public async virtual Task<T> GetByOneAsync(Expression<Func<T, bool>> where, string tableName)
        {
            var runsql = DbType.DB().GetGuidRepository<T>(null, oldName => tableName);
            return await runsql.Select.Where(where).ToOneAsync();
        }

        /// <summary>
        /// 根据条件获取list
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public virtual List<T> GetList(Expression<Func<T, bool>> where, string tableName)
        {
            var runsql = DbType.DB().GetGuidRepository<T>(null, oldName => tableName);
            return runsql.Select.Where(where).ToList();
        }

        /// <summary>
        /// 查询方法
        /// </summary>
        /// <param name="where"></param>
        /// <param name="orderby"></param>
        /// <returns></returns>
        public async virtual Task<(List<T> list, long count)> QueryAsync(Expression<Func<T, bool>> where, string tableName,
             List<SortInfo<T, object>> orderbys = null, PageInfo pageInfo = null)
        {
            //设置查询条件
            var list = DbType.DB().GetGuidRepository<T>(null, oldName => tableName).Select.Where(where);

            var count = list.Count();

            //设置排序
            if (orderbys != null)
            {
                foreach (var item in orderbys)
                {
                    list = item.SortMethods == SortEnum.Asc ? list.OrderBy(item.Orderby) : list.OrderByDescending(item.Orderby);
                }
            }

            //设置分页操作
            if (pageInfo != null && pageInfo.IsPaging)
                list.Skip((pageInfo.PageIndex - 1) * pageInfo.PageSize).Limit(pageInfo.PageSize);
            var resultList = await list.ToListAsync();
            //执行查询
            return (resultList, count);
        }

        #region no Async


        /// <summary>
        /// 获取数量
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public virtual long Count(string tableName)
        {
            var runsql = DbType.DB().GetGuidRepository<T>(null, oldName => tableName).Select;
            return runsql.Count();
        }

        /// <summary>
        /// 新增方法
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public virtual T Insert(T model, string tableName)
        {
            var runsql = DbType.DB().GetGuidRepository<T>(null, oldName => tableName);
            return runsql.Insert(model);
        }


        /// <summary>
        /// 新增方法
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public virtual List<T> BatchInsert(List<T> models, string tableName)
        {
            var runsql = DbType.DB().GetGuidRepository<T>(null, oldName => tableName);
            return runsql.Insert(models);
        }

        /// <summary>
        /// 修改方法
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public virtual bool Update(T model, string tableName)
        {
            var runsql = DbType.DB().GetGuidRepository<T>(null, oldName => tableName);
            int rows = runsql.Update(model);

            return rows > 0;
        }

        /// <summary>
        /// 删除方法
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual bool Delete(Guid id, string tableName)
        {
            var runsql = DbType.DB().GetGuidRepository<T>(null, oldName => tableName);
            var result = runsql.Delete(id);
            return result > 0;
        }

        /// <summary>
        /// 删除方法
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual bool Delete(Expression<Func<T, bool>> where, string tableName)
        {
            var runsql = DbType.DB().GetGuidRepository<T>(null, oldName => tableName);
            var result = runsql.Delete(where);
            return result > 0;
        }



        /// <summary>
        /// 获取一条数据
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public virtual T GetByOne(Expression<Func<T, bool>> where, string tableName)
        {
            var runsql = DbType.DB().GetGuidRepository<T>(null, oldName => tableName);
            return runsql.Select.Where(where).ToOne();
        }




        /// <summary>
        /// 查询方法
        /// </summary>
        /// <param name="where"></param>
        /// <param name="orderby"></param>
        /// <returns></returns>
        public virtual (List<T> list, long count) Query(Expression<Func<T, bool>> where, string tableName,
             List<SortInfo<T, object>> orderbys = null, PageInfo pageInfo = null)
        {
            //设置查询条件
            var list = DbType.DB().GetGuidRepository<T>(null, oldName => tableName).Select.Where(where);

            var count = list.Count();

            //设置排序
            if (orderbys != null)
            {
                foreach (var item in orderbys)
                {
                    list = item.SortMethods == SortEnum.Asc ? list.OrderBy(item.Orderby) : list.OrderByDescending(item.Orderby);
                }
            }

            //设置分页操作
            if (pageInfo != null && pageInfo.IsPaging)
                list.Skip((pageInfo.PageIndex - 1) * pageInfo.PageSize).Limit(pageInfo.PageSize);
            var resultList = list.ToList();
            //执行查询
            return (resultList, count);
        }
        /// <summary>
        /// 执行查询sql
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public List<T> QueryBySql(string sql, string tableName)
        {
            return DbType.DB().GetGuidRepository<T>(null, oldName => tableName).Select.Where(sql).ToList();
        }

        /// <summary>
        /// 执行自定义查询sql 分页查询
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="startIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public List<T> QueryBySqlPage(string sql, int startIndex, int pageSize, string tableName)
        {
            return DbType.DB().GetGuidRepository<T>(null, oldName => tableName).Select.WithSql(sql).Page(startIndex, pageSize).ToList();
        }



        #endregion
        #endregion
    }
}

